#include <utils/cutils.h>
#include <utils/cconfig.h>

int16_t (CUtils::*BigShort)(int16_t s);
int16_t (CUtils::*LittleShort)( int16_t s);
int32_t (CUtils::*BigLong)(int32_t l);
int32_t (CUtils::*LittleLong)(int32_t l);
float (CUtils::*BigFloat)(float f);
float (CUtils::*LittleFloat)(float f);
double (CUtils::*BigDouble)(double d);
double (CUtils::*LittleDouble)(double d);

CUtils *g_Utils;
CConfig *g_Config;

void CUtils::InitUtils()
{
    // Test Endian

    union
    {
        uint32_t i;
        char c[4];
    } data = {0x01020304};

    if (data.c[0] == 1)
    {
        // Big Endian

        BigShort = &CUtils::ShortNoSwap;
        LittleShort = &CUtils::ShortSwap;
        BigLong = &CUtils::LongNoSwap;
        LittleLong = &CUtils::LongSwap;
        BigFloat = &CUtils::FloatNoSwap;
        LittleFloat = &CUtils::FloatSwap;
        BigDouble = &CUtils::DoubleNoSwap;
        LittleDouble = &CUtils::DoubleSwap;
    }
    else
    {
        // Little Endian

        BigShort = &CUtils::ShortSwap;
        LittleShort = &CUtils::ShortNoSwap;
        BigLong = &CUtils::LongSwap;
        LittleLong = &CUtils::LongNoSwap;
        BigFloat = &CUtils::FloatSwap;
        LittleFloat = &CUtils::FloatNoSwap;
        BigDouble = &CUtils::DoubleSwap;
        LittleDouble = &CUtils::DoubleNoSwap;
    }
}

int16_t CUtils::ShortSwap(int16_t s)
{
    unsigned char b1;
    unsigned char b2;

    b1 = s & 255;
    b2 = (s >> 8) & 255;
    return (b1 << 8) + b2;
}

int16_t CUtils::ShortNoSwap(int16_t s)
{
    return s;
}

int32_t CUtils::LongSwap(int32_t l)
{
    unsigned char b1;
    unsigned char b2;
    unsigned char b3;
    unsigned char b4;

    b1 = l & 255;
    b2 = (l >> 8) & 255;
    b3 = (l >> 16) & 255;
    b4 = (l >> 24) & 255;
    return ((int32_t) b1 << 24) + ((int32_t) b2 << 16) + ((int32_t) b3 << 8) + b4;
}

int32_t CUtils::LongNoSwap(int32_t l)
{
    return l;
}

float CUtils::FloatSwap(float f)
{
    union
    {
        float f;
        unsigned char b[4];
    } dat1, dat2;

    dat1.f = f;
    dat2.b[0] = dat1.b[3];
    dat2.b[1] = dat1.b[2];
    dat2.b[2] = dat1.b[1];
    dat2.b[3] = dat1.b[0];
    return dat2.f;
}

float CUtils::FloatNoSwap(float f)
{
    return f;
}

double CUtils::DoubleSwap(double d)
{
    union
    {
        double d;
        unsigned char b[8];
    } dat1, dat2;

    dat1.d = d;
    dat2.b[0] = dat1.b[7];
    dat2.b[1] = dat1.b[6];
    dat2.b[2] = dat1.b[5];
    dat2.b[3] = dat1.b[4];
    dat2.b[4] = dat1.b[3];
    dat2.b[5] = dat1.b[2];
    dat2.b[6] = dat1.b[1];
    dat2.b[7] = dat1.b[0];
    return dat2.d;
}

double CUtils::DoubleNoSwap(double d)
{
    return d;
}
